using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XboxShmup
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        enum GameStates
        {
            Starting,
            Playing,
            Pausing,
            GameOver
        }
        GameStates currentState;
        List<Projectile> projectileList = new List<Projectile>();
        List<Projectile> projectileCleanupList = new List<Projectile>();
        List<Enemy> EnemyCleanupList = new List<Enemy>();
        List<Enemy> enemyList = new List<Enemy>();
        List<EnemyProjectile> enemyProjectileList = new List<EnemyProjectile>();
        List<EnemyProjectile> enemyProjectileCleanupList = new List<EnemyProjectile>();
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Ship PlayerShip;

        private bool bIsPaused = false;
        Texture2D enemyTexture;
        Texture2D colorBlock;
        Texture2D mainBackground;
        BackGround bglayer1;
        BackGround bgLayer2;
        GamePadState playerOneGamepad;
        SpriteFont scoreFont;
        double rateOfFire = 75;
        double elapsedTime = 0;
        public int playerScore = 0;
        Rectangle HealthBarRectangle;
        const int HEALTH_BAR_WIDTH = 250;
        const int HEALTH_BAR_HEIGHT = 20;
        double enemySpawnTime;
        double rateOfSpawn = 2;
        double defaultSpawnRate = 2;
        double maxSpawnRate = .75;
        double spawnRateIncrease = 0.1f;
        double spawnRateIncreaseTimer;
        double spawnRateIncreaseTimerMax = 3;
        Random random;
        public double spawnRateForEnemy;
        public int enemyHealth;

        SoundEffect LaserSoundEffect;
        Song BackgroundMusic;
        private string CenterScreenText;
        private Vector2 CenterScreenTextPositin;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            spawnRateIncreaseTimer = spawnRateIncreaseTimerMax;
            PlayerShip = new Ship(this, 0, 0);
            PlayerShip.Initialize();
            bgLayer2 = new BackGround();
            bglayer1 = new BackGround();
            enemyList = new List<Enemy>();
            rateOfSpawn = defaultSpawnRate;
            HealthBarRectangle = new Rectangle(GraphicsDevice.Viewport.Width / 2 - HEALTH_BAR_WIDTH / 2, GraphicsDevice.Viewport.Height - 20, HEALTH_BAR_WIDTH, HEALTH_BAR_HEIGHT);
            currentState = GameStates.Starting;
            playerScore = 0;
            random = new Random();

            base.Initialize();
        }

        public void Lose()
        {
            currentState = GameStates.GameOver;
        }


        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(GraphicsDevice);
            bglayer1.Initialize(Content, "bglayer1", GraphicsDevice.Viewport.Width, -1);
            bgLayer2.Initialize(Content, "bgLayer2", GraphicsDevice.Viewport.Width, -2);
            enemyTexture = Content.Load<Texture2D>("mineAnimation");
            mainBackground = Content.Load<Texture2D>("mainbackground");
            scoreFont = Content.Load<SpriteFont>("Score");
            colorBlock = Content.Load<Texture2D>("coloredBlock");
            LaserSoundEffect = Content.Load<SoundEffect>("LaserSound");
            BackgroundMusic = Content.Load<Song>("I am the Doctor");
            MediaPlayer.IsRepeating = true;
            MediaPlayer.Volume = 1;
            MediaPlayer.Play(BackgroundMusic);
            AddEnemy();
            PlayerShip.LoadContent();

        }
        protected override void UnloadContent()
        {

        }

        private void AddEnemy()
        {
            Vector2 position = new Vector2(GraphicsDevice.Viewport.Width, random.Next(10, GraphicsDevice.Viewport.Height - 100));
            enemyList.Add(new SpaceShipEnemyTypeA(this, (int)position.X, (int)position.Y));

        }


        protected override void Update(GameTime gameTime)
        {

            

            switch (currentState)
            {
                case GameStates.Starting:
                    StartingUpdate(gameTime);
                    break;

                case GameStates.Playing:
                    GameplayUpdate(gameTime);
                    break;
                case GameStates.GameOver:
                    GameOverUpdate(gameTime);
                    break;
            }

            base.Update(gameTime);
        }

        private void GameOverUpdate(GameTime gameTime)
        {
            CenterScreenText = "You Lost";

            RecenterCenterText();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Start == ButtonState.Pressed)
            {
                CenterScreenText = "";
                RestartGame();
            }

        }

        private void RestartGame()
        {
            EnemyCleanupList.Clear();
            projectileCleanupList.Clear();
            enemyProjectileList.Clear();
            enemyProjectileCleanupList.Clear();
            projectileList.Clear();
            enemyList.Clear();
            Initialize();
            currentState = GameStates.Starting;
        }
        public void StartingUpdate(GameTime gameTime)
        {
            CenterScreenText = "PRESS START TO BEGIN THE GAME!";
            RecenterCenterText();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Start == ButtonState.Pressed)
            {
                bIsPaused = false;
                CenterScreenText = "";
                currentState = GameStates.Playing;
            }
        }

        private void RecenterCenterText()
        {
            CenterScreenTextPositin = new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            CenterScreenTextPositin -= scoreFont.MeasureString(CenterScreenText) / 2;
        }
        private void GameplayUpdate(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                bIsPaused = true;
            if (!bIsPaused)
            {
                // Allows the game to exit
                ProssesInput(gameTime);

                PlayerShip.Update(gameTime);
                spawnRateIncreaseTimer -= gameTime.ElapsedGameTime.TotalSeconds;
                if (spawnRateIncreaseTimer <= 0)
                {
                    spawnRateIncreaseTimer = spawnRateIncreaseTimerMax;
                    rateOfSpawn -= spawnRateIncrease;
                    if (rateOfSpawn <= maxSpawnRate)
                        rateOfSpawn = maxSpawnRate;
                }
                foreach (Enemy enemy in enemyList)
                {
                    enemy.Update(gameTime);
                    enemy.CheckCollisionWith(PlayerShip);
                }
                foreach (Projectile projectile in projectileList)
                {
                    projectile.Update(gameTime);
                    foreach (Enemy enemy in enemyList)
                    {
                        if (projectile.CheckCollisionWith(enemy))
                            projectile.bCleanUp = true;
                    }
                    if (projectile.bCleanUp)
                    {
                        projectileCleanupList.Add(projectile);
                    }
                }
                foreach (Projectile projectile in projectileCleanupList)
                {
                    projectileList.Remove(projectile);
                }
                projectileCleanupList.Clear();
                foreach (EnemyProjectile enemyProjectile in enemyProjectileList)
                {
                    enemyProjectile.Update(gameTime);
                    if (enemyProjectile.CheckCollisionWith(PlayerShip))
                        enemyProjectile.bCleanUp = true;
                    if (enemyProjectile.bCleanUp)
                        enemyProjectileCleanupList.Add(enemyProjectile);
                }
                foreach (EnemyProjectile enemyProjectile in enemyProjectileCleanupList)
                {
                    enemyProjectileList.Remove(enemyProjectile);
                }
                enemyProjectileCleanupList.Clear();
                foreach (Enemy enemy in enemyList)
                {
                    if (enemy.bCleanUp)
                    {
                        EnemyCleanupList.Add(enemy);
                    }
                }
                foreach (Enemy enemy in EnemyCleanupList)
                {
                    enemyList.Remove(enemy);
                }

                bglayer1.Update();
                bgLayer2.Update();
                UpdateHealthBar();
                if (playerOneGamepad.IsButtonDown(Buttons.LeftTrigger))
                    PlayerShip.speed = 1000;
                else
                    PlayerShip.speed = 500;
            }
            else
            {

                CenterScreenText = "PRESS START TO RESUME THE GAME!";
                RecenterCenterText();
                if (GamePad.GetState(PlayerIndex.One).Buttons.Start == ButtonState.Pressed)
                {
                    bIsPaused = false;
                    CenterScreenText = "";
                }
            }
        }

        public void ProssesInput(GameTime gametime)
        {
            playerOneGamepad = GamePad.GetState(PlayerIndex.One);
            PlayerShip.MoveShip(playerOneGamepad.ThumbSticks.Left, gametime);
            elapsedTime += gametime.ElapsedGameTime.TotalMilliseconds;
            if (elapsedTime >= rateOfFire)
            {
                elapsedTime = 0;
                if (playerOneGamepad.IsButtonDown(Buttons.RightTrigger))
                {
                    Vector2 movementVector = new Vector2(1, 0);
                    ShootProjectile(movementVector);
                }
            }
            enemySpawnTime += gametime.ElapsedGameTime.TotalSeconds;
            if (enemySpawnTime >= rateOfSpawn)
            {
                enemySpawnTime = 0;
                AddEnemy();
            }
        }

        private void ShootProjectile(Vector2 movementVector)
        {
            LaserSoundEffect.Play(0.5f,0,0);
            projectileList.Add(new Projectile(this, (int)PlayerShip.position.X + PlayerShip.boundingBox.Width, (int)PlayerShip.position.Y + (PlayerShip.boundingBox.Height / 2), movementVector));
        }

        public void ShootEnemyProjectile(Vector2 movementVector, Vector2 position)
        {
            enemyProjectileList.Add(new EnemyProjectile(this, (int)position.X, (int)position.Y, movementVector));
        }

        public void UpdateHealthBar()
        {
            float healthPercent;
            healthPercent = (float)PlayerShip.playerHealth / (float)Ship.MAX_HEALTH;
            HealthBarRectangle.Width = (int)((float)HEALTH_BAR_WIDTH * healthPercent);
        }

        protected override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(mainBackground, Vector2.Zero, Color.LightSteelBlue);
            bglayer1.Draw(spriteBatch);
            bgLayer2.Draw(spriteBatch);

            PlayerShip.DrawSprite(spriteBatch);
            foreach (Projectile projectile in projectileList)
            {
                projectile.DrawSprite(spriteBatch);
            }
            foreach (EnemyProjectile enemyProjectile in enemyProjectileList)
            {
                enemyProjectile.DrawSprite(spriteBatch);
            }
            foreach (Enemy enemy in enemyList)
            {
                enemy.DrawSprite(spriteBatch);
            }

            spriteBatch.Draw(colorBlock, HealthBarRectangle, Color.Red);
            spriteBatch.DrawString(scoreFont, CenterScreenText, CenterScreenTextPositin, Color.WhiteSmoke);
            spriteBatch.DrawString(scoreFont, playerScore.ToString(),new Vector2(20,20), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
